package gwtadmin.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownServiceException;

/**
 * This class provide API for Swordfish Service Registry.
 * It uses REST interface of Registry.
 * 
 */
public class ServiceRegistry {
	
	public String host = "localhost:9001";
	
	public ServiceRegistry(String host_) {
		host = host_;
	}
	
	public String getHost() {
		return host;
	}
	
	/**
	 * Checks status of Service Registry.
	 * @return <b>True</b> if Registry is online. <b>False</b> if Registry is offline.
	 */
	public boolean isRegistryUp() {
		try {
			URL url = new URL("http://" + host + "/registry/wsdl");
			HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
			
			urlConnect.setRequestMethod("HEAD");
			urlConnect.setRequestProperty("Connection", "close");
			int res = urlConnect.getResponseCode();
			urlConnect.disconnect();
			
			if (res != 200)
				return false;
		} catch (RuntimeException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		
		return true;
	}
	
	/**
	 * Gets list of wsdl files on Service Registry.
	 * @return List of wsdl files in format of Service Registry.
	 */
	public String getWsdlList() {
		try {
			URL url = new URL("http://" + host + "/registry/wsdl");
			HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
			
			urlConnect.setRequestMethod("GET");
//			urlConnect.setRequestProperty("Connection", "close");
			urlConnect.setRequestProperty("Accept", "text/plain");

			byte[] buff = readData(urlConnect);
			urlConnect.disconnect();
			
			return new String(buff);
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return "";
	}
	
	/**
	 * Gets list of wsdl files that contains specific port type.
	 * @param name - name of port type.
	 * @param namespace - namespace of port type name.
	 * @return List of wsdl files in format of Service Registry.
	 */
	public String getWsdlListPortType(String name, String namespace) {
		try {
			URL url = new URL("http://" + host + "/registry/wsdl?type=portType&targetNamespace=" + namespace +
					"&name=" + name);
			HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
			
			urlConnect.setRequestMethod("GET");
//			urlConnect.setRequestProperty("Connection", "close");
			urlConnect.setRequestProperty("Accept", "text/plain");

			byte[] buff = readData(urlConnect);
			urlConnect.disconnect();
			
			return new String(buff);
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return "";
	}
	
	/**
	 * Gets list of wsdl files that contains services that implements specific port type.
	 * @param name - name of port type.
	 * @param namespace - namespace of port type name.
	 * @return List of wsdl files in format of Service Registry.
	 */
	public String getWsdlListService(String name, String namespace) {
		try {
			URL url = new URL("http://" + host + "/registry/wsdl?type=service&refPortTypeNamespace=" + namespace +
					"&refPortTypeName=" + name);
			HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
			
			urlConnect.setRequestMethod("GET");
//			urlConnect.setRequestProperty("Connection", "close");
			urlConnect.setRequestProperty("Accept", "text/plain");

			byte[] buff = readData(urlConnect);
			urlConnect.disconnect();
			
			return new String(buff);
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return "";
	}
	
	/**
	 * Gets content of specific wsdl file.
	 * @param fileName - name of wsdl file.
	 * @return Content of wsdl file.
	 */
	public String getWsdlFile(String fileName) {
		try {
			URL url = new URL("http://" + host + "/registry/wsdl/" + fileName);
			HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection();
			
//			urlConnect.setRequestMethod("GET");
//			urlConnect.setRequestProperty("Connection", "close");
			
			byte[] buff = readData(urlConnect);
			urlConnect.disconnect();

			return new String(buff);
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return "";
	}
	
	/**
	 * Removes specific wsdl file from Service Registry.
	 * @param fileName - name of wsdl file.
	 * @return true if wsdl file is removed, otherwise returns false.
	 */
	public boolean removeWsdlFile(String fileName) {
		try {
			URL url = new URL("http://" + host + "/registry/wsdl/" + fileName);
			HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();

			urlConnect.setDoOutput(false);
			urlConnect.setRequestMethod("DELETE");
			urlConnect.setRequestProperty("Accept", "*/*");
			urlConnect.setRequestProperty("Connection", "close");
			urlConnect.getResponseCode();
			urlConnect.disconnect();
			
			return true;
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return false;
		} catch (UnknownServiceException e) {
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}
	
	/**
	 * Uploads wsdl file into Service Registry.
	 * @param fileName - name of wsdl file to store in Service Registry.
	 * @param wsdlFile - content of wsdl file.
	 * @return true if wsdl file is uploaded, otherwise returns false.
	 */
	public boolean uploadWsdlFile(String fileName, String wsdlFile) {
//		System.out.println(wsdlFile);
		try {
			URL url = new URL("http://" + host + "/registry/wsdl/" + fileName);
			HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
			
			urlConnect.setInstanceFollowRedirects(false);
			urlConnect.setDoOutput(true);
			urlConnect.setRequestMethod("PUT");
			urlConnect.setRequestProperty("Connection", "close");
			urlConnect.setRequestProperty("Content-Length", String.valueOf(wsdlFile.length()));
			urlConnect.setRequestProperty("Content-Type", "application/xml; charset=UTF-8");
			
			urlConnect.connect();

			OutputStream os = urlConnect.getOutputStream();
			os.write(wsdlFile.getBytes());
			os.close();
		
			return (urlConnect.getResponseCode() == 400);
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return false;
		} catch (UnknownServiceException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}
	
	////////////////////////////////////////////////////////////////////////

	private static byte[] readData(URLConnection conn) throws IOException {
		return readData(conn.getInputStream(), conn.getContentLength());
	}
	
	private static byte[] readData(InputStream is, int length) throws IOException {
		byte[] data = new byte[length];
		int rd = is.read(data);
		while (rd < data.length && rd != -1) {
			rd = is.read(data, rd, data.length - rd);
		}
		is.close();

		return data;
	}
}
